// 串行全比较排序法在并行全比较排序法做了一些改进，将原来并行全比较排序法的前三个周期由并行转变为串行，
// 但是可以在比较的同时将得分累加，所以串行全比较排序法排序需要的周期是2*m（m个序列）个周期。
module sort_32_u8 #(
           parameter W_DATA = 8 ,
           parameter NUM = 32

       ) (
           input wire clk ,         //系统时钟
           input wire rst_n ,         //系统异步复位，低电平有效
           input wire vld_in ,         //输入数据有效指示
           input wire [W_DATA - 1: 0] din_0 , din_1 , din_2 , din_3 , din_4 , din_5 , din_6 , din_7 , din_8 , din_9 ,
           din_10, din_11, din_12, din_13, din_14, din_15, din_16, din_17, din_18, din_19 ,
           din_20, din_21, din_22, din_23, din_24, din_25, din_26, din_27, din_28, din_29 ,
           din_30, din_31 ,          //输入数据0，输入数据1，……， 输入数据31
           output reg vld_out ,         //输出数据有效指示
           output wire [W_DATA - 1: 0] dout_0 , dout_1 , dout_2 , dout_3 , dout_4 , dout_5 , dout_6 , dout_7 , dout_8 , dout_9 ,
           dout_10, dout_11, dout_12, dout_13, dout_14, dout_15, dout_16, dout_17, dout_18, dout_19 ,
           dout_20, dout_21, dout_22, dout_23, dout_24, dout_25, dout_26, dout_27, dout_28, dout_29 ,
           dout_30, dout_31  //输出数据0，输出数据1，……， 输出数据31
       );

reg [$clog2(NUM): 0] score;
reg [$clog2(NUM): 0] comp_cnt;
reg [$clog2(NUM): 0] col;
reg valid_o, valid_r, valid_rr;

wire [W_DATA - 1: 0] din [NUM - 1: 0];
assign {
        din[0 ], din[1 ], din[2 ], din[3 ], din[4 ], din[5 ], din[6 ], din[7 ], din[8 ], din[9 ] ,
        din[10], din[11], din[12], din[13], din[14], din[15], din[16], din[17], din[18], din[19] ,
        din[20], din[21], din[22], din[23], din[24], din[25], din[26], din[27], din[28], din[29] ,
        din[30], din[31]
    } = {
        din_0 , din_1 , din_2 , din_3 , din_4 , din_5 , din_6 , din_7 , din_8 , din_9 ,
        din_10, din_11, din_12, din_13, din_14, din_15, din_16, din_17, din_18, din_19 ,
        din_20, din_21, din_22, din_23, din_24, din_25, din_26, din_27, din_28, din_29 ,
        din_30, din_31
    };

always@(posedge	clk	or posedge	rst_n)
	begin
		if (!rst_n)
			begin
				comp_cnt <= NUM + 1;
				score <= 1;
				valid_o <= 0;
				col <= 0;
			end
		else	if (vld_in && comp_cnt <= NUM)
			begin
				comp_cnt <= comp_cnt + 1;

				if (din[col] > din[comp_cnt])
					score <= score;
				else	if (din[col] == din[comp_cnt])
					begin
						if (col <= comp_cnt)
							score <= score;
						else
							score <= score + 1;
					end
				else
					score <= score + 1;

				if (comp_cnt == NUM)
					valid_o <= 1;
				else
					valid_o <= 0;
			end
		else	if (vld_in && valid_r)
			begin
				comp_cnt <= 0;
				score <= 1;
				valid_o <= 0;
				col <= col + 1'b1;
			end
		else	if (vld_in && valid_rr)
			begin
				comp_cnt <= 0;
				score <= 1;
				valid_o <= 0;
				col <= 0;
			end
		else
			begin
				comp_cnt <= comp_cnt;
				score <= score;
				valid_o <= 0;
			end
	end

reg [$clog2(NUM): 0] sum [NUM - 1: 0];

integer i, j;

always@(posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			begin
				for (i = 0;i < NUM;i = i + 1)
					begin
						sum[i] <= 0;
					end
			end
		else if (valid_o && col != NUM)
			begin
				sum[score] <= din[col];
				valid_r <= 1'b1;
				valid_rr <= 1'b0;
			end
		else if (valid_o && col == NUM)
			begin
				sum[score] <= din[col];
				vld_out <= 1'b1;
				valid_rr <= 1'b1;
			end
		else
			begin
				valid_r <= 1'b0;
			end
	end

assign {
        dout_0 , dout_1 , dout_2 , dout_3 , dout_4 , dout_5 , dout_6 , dout_7 , dout_8 , dout_9 ,
        dout_10, dout_11, dout_12, dout_13, dout_14, dout_15, dout_16, dout_17, dout_18, dout_19 ,
        dout_20, dout_21, dout_22, dout_23, dout_24, dout_25, dout_26, dout_27, dout_28, dout_29 ,
        dout_30, dout_31
    } = {
        sum[0 ], sum[1 ], sum[2 ], sum[3 ], sum[4 ], sum[5 ], sum[6 ], sum[7 ], sum[8 ], sum[9 ] ,
        sum[10], sum[11], sum[12], sum[13], sum[14], sum[15], sum[16], sum[17], sum[18], sum[19] ,
        sum[20], sum[21], sum[22], sum[23], sum[24], sum[25], sum[26], sum[27], sum[28], sum[29] ,
        sum[30], sum[31]
    } ;
endmodule
